// Symbol 基本类型  独一无二的值, 传入的参数智能是number和string  不能做运算
// const s = Symbol()   // 不需要使用new
// console.log(s);  // Symbol()

// const s2 = Symbol()
// console.log(s2); 
// // console.log(s === s2) // 直接报错

// const s3 = Symbol('lison')  // 传入一个标识, 方便后期的维护
// console.log(s3);  // Symbol('lison')

// const s4 = Symbol('lison')   // Symbol(lison)
// console.log(s4.toString())   // Symbol(lison)
// console.log(Boolean(s4))     // true
// console.log(!s4)             // false

// let prop = 'name'
// const info = {
//   // name: 'lison'
//   [prop]: 'lison'
// }

// console.log(info);

// const s5 = Symbol('name')
// const info2 = {
//   [s5]: 'lison',
//   age: 18,
//   sex: 'man'
// }

// console.log(info2);

// info2[s5] = 'haha'  // 不可以使用.

// console.log(info2[s5]);

// for (const key in info2) {
//   console.log(key)
// }

// console.log(Object.keys(info2));   // 获取不到Symbol属性名

// console.log(Object.getOwnPropertyNames(info2));     // 获取不到Symbol属性名

// console.log(JSON.stringify(info2));     // 获取不到Symbol属性名

// console.log(Object.getOwnPropertySymbols(info2));  // 只获取到symbol属性

// console.log(Reflect.ownKeys(info2));   // 可以获取所有属性

// Symbol.for() 在全局创建一个Symbol值        Symbol.keyFor()

// const s6 = Symbol('lison')
// const s7 = Symbol('lison')  // s6和s7是不相等的

// const s8 = Symbol.for('lison')
// const s9 = Symbol.for('lison')  // s8和s9是相等的   它会先判断全局变量有没有这个Symbol值，如果有直接把值赋给s9，没有就创建一个新的Symbol
// const s10 = Symbol.for('haha')  //s10和s9是不相等的


// console.log(Symbol.keyFor(s8));   // 获取用Symbol.for创建的Symbol值， 如果是不Symbol.for创建的则是undefined


// // Symbol.hasInstance 用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个类上的行为。

// const obj1 = {
//   [Symbol.hasInstance] (otherObj: any) {
//     console.log(otherObj);
//   }
// }
// console.log({ a: 'a'} instanceof <any>obj1);     // false

// // Symbol.isConcatSpreadabel  内置的Symbol.isConcatSpreadable符号用于配置某对象作为Array.prototype.concat()方法的参数时是否展开其数组元素。
// // 简单点说就是当使用concat时，设置这个值为false时，不是扁平化的


// let arr: any = [1, 2]
// let myrr: any = []
// console.log(myrr.concat(arr, [3, 4]));  // [1, 2, 3, 4]
// console.log(arr[Symbol.isConcatSpreadable]);   // 默认值为undefined
// arr[Symbol.isConcatSpreadable] = false
// console.log(myrr.concat(arr, [3, 4]));  //  [Array(2), 3, 4]


class C extends Array {
  constructor (...args: any) {
    super(...args)
  }
  static get [Symbol.species] () {  // 如果es6中去掉这个， a就是C的实例对象 **和es6的区别
    return Array
  }
  getName () {
    return 'lison'
  }
}

const c = new C(1, 2, 3)
// console.log(c);   // [1, 2, 3]

const a = c.map( (item: number) => item + 1)
// console.log(a);  [2, 3, 4]
// console.log(a instanceof C);    // false

let obj3 = {
  [Symbol.match] (string: string) {   // 指定了匹配的是正则表达式而不是字符串。String.prototype.match() 方法会调用此函数。
    // console.log(string.length);    
  },
  [Symbol.split] (string: string) {
    // console.log('split', string.length);    
  }
}

'abcde'.match(<RegExp>obj3)
'abcde'.split(<any>obj3)

// Symbol.replace
// Symbol.search
// Symbol.split

let obj4: unknown = {
  [Symbol.toPrimitive] (type: any) {
    console.log(type);    
  }
}
// const res = (obj4 as number)++   // number
const res = `abc${obj4}`  // default  如果是在js中打印的是 string（和js的区别）

// Symbol.toStringTag 是一个内置 symbol，它通常作为对象的属性键使用，对应的属性值应该为字符串类型，这个字符串用来表示该对象的自定义类型标签，通常只有内置的 Object.prototype.toString() 方法会去读取这个标签并把它包含在自己的返回值里。
let obj5 = {
  // [Symbol.toStringTag]: 'lison'
  get [Symbol.toStringTag] () {
    return 'lison'
  }
}

console.log(obj5.toString());  // [object lison]







